package core

import (
	"encoding/json"
	"github.com/imroc/req"
	errors2 "github.com/pkg/errors"
	"hpmGo/constants"
	"hpmGo/utils"
	"io/ioutil"
	"os"
	"path/filepath"
)

type Manifest struct {
	Name         string            `json:"name"`
	Version      string            `json:"version"`
	PublishAs    string            `json:"publishAs" survery:"publishAs"`
	Description  string            `json:"description"`
	License      string            `json:"license"`
	Private      bool              `json:"private"`
	Repository   string            `json:"repository"`
	Tags         []string          `json:"tags"`
	Keywords     []string          `json:"keywords"`
	Scripts      Scripts           `json:"scripts"`
	Dependencies map[string]string `json:"dependencies"`
	Segment      Segment           `json:"segment"`
	Ohos         Ohos              `json:"ohos"`
	Url          string
}

func (m *Manifest) SaveToJson(path string) error {
	s, err := json.MarshalIndent(m, "", "    ")
	if err != nil {
		return errors2.Errorf("SaveToJson Failed: Marshal json failed %v", err)
	}
	err = ioutil.WriteFile(filepath.Join(path, "bundle.json"), s, 0666)
	if err != nil {
		return errors2.Errorf("SaveToJson Failed: write json to file failed %v", err)
	}
	return nil
}

func (m *Manifest) Install(path string) error {
	r, err := req.Get(m.Url)
	err = r.ToFile(path)
	if err != nil {
		return errors2.Errorf("Install failed: %v", err)
	}
	return nil
}

func (m *Manifest) UpdateDependencies(params []string) {
	for _, param := range params {
		key, version := ParseArg(param)
		m.Dependencies[key] = version
	}
}

func (m *Manifest) DeleteDependencies(keys []string) {
	for _, key := range keys {
		delete(m.Dependencies, key)
	}
}

func (m Manifest) CopySegment() error {
	if m.Segment.DestPath != "" {
		cwd, _ := os.Getwd()
		destPath := filepath.Join(cwd, m.Segment.DestPath)
		if !utils.Exists(destPath) {
			if err := utils.CreateDir(destPath); err != nil {
				return err
			}
		}
		sourcePath := filepath.Join(cwd, constants.OHOS_BUNDLES, m.Name)
		err := utils.CopyDir(sourcePath, destPath)
		if err != nil {
			return err
		}
	}
	return nil
}

func FromDetailManifest(d Detail) Manifest {
	m := d.Manifest
	m.Url = d.Download.Addr
	m.Dependencies = make(map[string]string)
	return m
}

func FromBundleJson(path string) (Manifest, error) {
	f, err := os.Open(path)
	if err != nil {
		return Manifest{}, errors2.WithMessage(err, "FromBundleJson error: Open bundle.json failed")
	}
	defer func() {
		err := f.Close()
		if err != nil {
			panic(err)
		}
	}()
	data, _ := ioutil.ReadAll(f)
	var m Manifest
	m.Dependencies = make(map[string]string)
	err = json.Unmarshal(data, &m)
	if err != nil {
		return Manifest{}, errors2.WithMessage(err, "FromBundleJson error: json parse failed")
	}
	return m, nil
}
